﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Sharpie.Libs;

namespace Sharpie
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Main : Microsoft.Xna.Framework.Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        protected float LogoScale = 0.6F;
        protected double LogoRadians = 0D;
        protected float LogoRotate = 0F;
        private Texture2D logo, menubackground, cursor, touchcircle;
        private Point mousecursor;
        private TouchLocation Touch;
        public static TouchPanelCapabilities TouchCapabilities = TouchPanel.GetCapabilities();
        private MapEditor mapeditor;
        private Textbox nicktextbox;
        private Dialog about, instruct;
        private Color curcolor;
        private SpriteFont FontNormal, FontSmall, FontBig;
        private GameEngine engine;
        private Menu mainmenu, diffmenu, settmenu, nickmenu, scolormenu, scoresmenu, instrmenu, aboutmenu, quitmenu, mapmenu, custmapmenu, nocustmapsmenu, langmenu;
        private ScrollableMenu custmaplist, langlist;
        public static LinkedList<MenuMode> menumode = new LinkedList<MenuMode>();
        public static GameMode gamemode = GameMode.MENU;
        private List<Map> maplist;
        private Map mapToLoad;
        public string version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion;
        public static readonly string Mapspath = Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Sharpie", "Maps"));
        public string WindowTitle = "Sharpie";
        

        public Main()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        public enum GameMode
        {
            MENU,
            GAME,
            EDITOR,
        }

        public enum MenuMode
        {
            Main,
            Difficulty,
            MapSelect,
            CustMapSelect,
            NoCustMap,
            Settings,
            Language,
            SnakeColor,
            Nick,
            Scores,
            Instruct,
            About,
            Exit
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;
            graphics.ApplyChanges();
            Window.Title = WindowTitle;
            // TODO: Add your initialization logic here
            if (!Directory.Exists(Mapspath))
                Directory.CreateDirectory(Mapspath);
            this.TargetElapsedTime = TimeSpan.FromSeconds(1f / 60f);
            base.Initialize();
            menumode.AddFirst(MenuMode.Main);
            LocaleInit();
            DialogsInit();
            MenusInit();
        }

        private void LocaleInit()
        {
            bool CopyDefault = false;
			string defaultLangPath = Path.Combine(Locale.LangDir, Locale.defaultLang);
            if (!File.Exists(defaultLangPath))
            {
                CopyDefault = true;
            }
            else
            {
                if (File.ReadAllText(defaultLangPath) != new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Sharpie.Lang.en.xml")).ReadToEnd())
                {
                    CopyDefault = true;
                }
            }

            if (CopyDefault)
            {
                using (StreamWriter sw = File.CreateText(defaultLangPath))
                {
                    using (StreamReader sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Sharpie.Lang.en.xml")))
                    {
                        while (!sr.EndOfStream)
                        {
                            sw.WriteLine(sr.ReadLine());
                        }
                    }
                    sw.Flush();
                }
            }

            if (!Locale.LoadLang(Properties.Settings.Default.Language))
            {
                if (Properties.Settings.Default.Language == "")
                {
                    ChangeMode(MenuMode.Language);
                }
                Properties.Settings.Default.Language = Locale.defaultLang;
                Properties.Settings.Default.Save();
                Locale.LoadLang(Properties.Settings.Default.Language);
            }
        }

        private void DialogsInit()
        {
            about = new Dialog(410, 290, GraphicsDevice.Viewport.Height / 2 - 40, this);
            about.BackgroundColor = Color.Gray;
            instruct = new Dialog(410, 250, GraphicsDevice.Viewport.Height / 2 - 20, this);
            instruct.BackgroundColor = Color.Gray;
            
        }

        private void MenusInit()
        {
            mainmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            mainmenu.Entries = new List<string>(new string[] {
				"{NEW_GAME}",
                "{MAP_EDITOR}",
				"{SETTINGS}",
				"{INSTRUCTION}",
                "{SCORES}",
				"{ABOUT_GAME}",
				"",
				"{EXIT_GAME}"
			});
            mapmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            mapmenu.Entries = new List<string>(new string[] {
				"{MAP} 1",
				"{MAP} 2",
				"{MAP} 3",
				"{MAP} 4",
				"{CUSTOM_MAPS}",
				"",
				"{BACK}"
			});

            custmaplist = new ScrollableMenu(GraphicsDevice.Viewport.Height / 2 - 40, 290, this);
            custmaplist.Title = "{CHOOSE_MAP}:";
            custmaplist.BottomMargin = (int)(FontNormal.LineSpacing * 1.6F);
            custmaplist.BackgroundShow = false;
            custmapmenu = new Menu(custmaplist.GetBackgroundRectangle().Bottom - (int)(FontNormal.LineSpacing * 1.4F), this);
            custmapmenu.Entries = new List<string>(new string[] { "{BACK}" });
            custmapmenu.BackgroundShow = false;
            nocustmapsmenu = new Menu(mapmenu.GetBackgroundRectangle().Center.Y - 50, this);
            nocustmapsmenu.BackgroundColor = Color.Red;
            nocustmapsmenu.TextHoverColor = new Color(255, 138, 142);
            nocustmapsmenu.Transparency = 0.85F;
            nocustmapsmenu.Title = "{MAP_NOT_FOUND}";
            nocustmapsmenu.Initialize();
            diffmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            diffmenu.Entries = new List<string>(new string[] {
				"{DIFFICULTY_EASY}",
				"{DIFFICULTY_MEDIUM}",
				"{DIFFICULTY_HARD}",
				"",
				"{BACK}"
			});
            diffmenu.Title = "{DIFFICULTY_SELECT}:";
            settmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            settmenu.Entries = new List<string>(new string[] { "{LANGUAGE}", "{NICK}", "{SNAKE_COLOR}", "", "{BACK}" });
            settmenu.Title = Locale.String("SETTINGS");
            nickmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            nickmenu.Entries = new List<string>(new string[] { "", "", "{OK}", "{CANCEL}" });
            nickmenu.Title = Locale.String("NICK_ENTER") + ":";
            nicktextbox = new Textbox(new Point(nickmenu.XPos + 25, (int)(nickmenu.YPos + FontNormal.LineSpacing * 1.8F)), nickmenu.Width - 50, FontNormal, this);
            nicktextbox.TextAlign = Textbox.Align.Center;
            langlist = new ScrollableMenu(GraphicsDevice.Viewport.Height / 2 - 20, 240, this);
            langlist.Title = "{LANGUAGE}";
            langlist.BottomMargin = (int)(FontNormal.LineSpacing * 2.5F);
            langlist.BackgroundShow = false;
            langmenu = new Menu(this);
            langmenu.YPos = langlist.GetBackgroundRectangle().Bottom - langmenu.Height - 8;
            langmenu.Entries = new List<string>(new string[] { "{REFRESH}", "{BACK}" });
            langmenu.BackgroundShow = false;
            LangListLoad();
            scoresmenu = new Menu(GraphicsDevice.Viewport.Height / 2, this);
            instrmenu = new Menu(instruct.GetDialogRectangle().Bottom - (int)(FontNormal.LineSpacing * 1.4F), this);
            instrmenu.TextHoverColor = Color.LightGray;
            instrmenu.BackgroundShow = false;
            aboutmenu = new Menu(about.GetDialogRectangle().Bottom - (int)(FontNormal.LineSpacing * 1.4F), this);
            aboutmenu.TextHoverColor = Color.LightGray;
            aboutmenu.BackgroundShow = false;
            quitmenu = new Menu(GraphicsDevice.Viewport.Height / 2 + 30, this);
            quitmenu.Entries = new List<string>(new string[] { "{YES}", "{NO}" });
            quitmenu.Title = Locale.String("EXIT_GAME_CONFIRM");
            quitmenu.TextHoverColor = new Color(255, 138, 142);
            quitmenu.BackgroundColor = Color.Red;
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            FontNormal = Content.Load<SpriteFont>("Fonts\\14pt");
            FontSmall = Content.Load<SpriteFont>("Fonts\\8pt");
            FontBig = Content.Load<SpriteFont>("Fonts\\20pt");
            logo = Content.Load<Texture2D>("Images\\gamelogo");
            menubackground = Content.Load<Texture2D>("Images\\leaves");
            cursor = Content.Load<Texture2D>("Images\\gamecursor");
            touchcircle = Content.Load<Texture2D>("Images\\circle");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        private MouseState mouse;

        private void CursorUpdate()
        {
            mouse = Mouse.GetState();
            mousecursor = new Point(mouse.X, mouse.Y);

            if (mouse.LeftButton == ButtonState.Pressed)
                curcolor = new Color(140, 234, 140);
            else
                curcolor = Color.White;
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
		
        protected override void Update(GameTime gameTime)
        {
            CursorUpdate();

            if (IsActive)
            {
                float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

                LogoRadians += 0.06D;
                LogoScale += 0.0004F * (float)Math.Sin(LogoRadians);

                switch (gamemode)
                {
                    case GameMode.MENU:
                        switch (menumode.Last.Value)
                        {
                            case MenuMode.Main:
                                mainmenu.Update(gameTime);
                                if (mainmenu.Choosed)
                                {
                                    switch (mainmenu.SelectedNum)
                                    {
                                        case 0:
                                            ChangeMode(MenuMode.MapSelect);
                                            break;
                                        case 1:
                                            gamemode = GameMode.EDITOR;
                                            mapeditor = new Sharpie.MapEditor(this);
                                            break;
                                        case 2:
                                            ChangeMode(MenuMode.Settings);
                                            break;
                                        case 3:
                                            ChangeMode(MenuMode.Instruct);
                                            break;
                                        case 4:
                                            //ChangeMode(MenuMode.Scores);
                                            break;
                                        case 5:
                                            ChangeMode(MenuMode.About);
                                            break;
                                        case 7:
                                            mainmenu.Escaped = true;
                                            break;
                                    }
                                }
                                if (mainmenu.Escaped)
                                {
                                    ChangeMode(MenuMode.Exit);
                                }
                                break;

                            case MenuMode.MapSelect:
                                mapmenu.Update(gameTime);
                                if (mapmenu.Choosed)
                                {
                                    switch (mapmenu.SelectedNum)
                                    {
                                        case 0:
                                        case 1:
                                        case 2:
                                        case 3:
                                            ChangeMode(MenuMode.Difficulty);
                                            mapToLoad = new Map(Assembly.GetExecutingAssembly().GetManifestResourceStream("Sharpie.Maps.Map" + (mapmenu.SelectedNum + 1) + ".smf"));
                                            break;

                                        case 4:
                                            maplist = new List<Map>();

                                            foreach (string s in Directory.GetFiles(Mapspath))
                                            {
                                                if (Path.GetExtension(Path.Combine(Mapspath, s)) == ".smf")
                                                {
                                                    maplist.Add(new Map(File.Open(s, FileMode.Open)));
                                                }
                                            }
                                            if (maplist.Count > 0)
                                            {
                                                List<string> entries = new List<string>();
                                                List<string> tooltips = new List<string>();
                                                foreach (Map m in maplist)
                                                {
                                                    entries.Add(m.Title);
                                                    tooltips.Add(Locale.String("AUTHOR") + ": " + m.Author + "\n" + Locale.String("DESCRIPTION") + ": " + m.Description);
                                                }
                                                custmaplist.Entries = entries;
                                                custmaplist.Tooltips = tooltips;
                                                ChangeMode(MenuMode.CustMapSelect);
                                            }
                                            else
                                            {
                                                ChangeMode(MenuMode.NoCustMap);
                                            }
                                            break;
                                        case 6:
                                            mapmenu.Escaped = true;
                                            break;
                                    }
                                }
                                if (mapmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;

                            case MenuMode.CustMapSelect:
                                custmaplist.Update(gameTime);
                                custmapmenu.Update(gameTime);
                                if (custmapmenu.Choosed)
                                    PrevMode();
                                else if (custmaplist.Choosed)
                                {
                                    mapToLoad = maplist[custmaplist.SelectedNum];
                                    ChangeMode(MenuMode.Difficulty);
                                }
                                if (custmaplist.Escaped | custmapmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;

                            case MenuMode.NoCustMap:
                                nocustmapsmenu.Update(gameTime);
                                if (nocustmapsmenu.Choosed)
                                    PrevMode();
                                break;

                            case MenuMode.Difficulty:
                                diffmenu.Update(gameTime);
                                if (diffmenu.Choosed)
                                {
                                    GameDifficulty difficulty = new GameDifficulty();
                                    switch (diffmenu.SelectedNum)
                                    {
                                        case 0:
                                            difficulty = GameDifficulty.Easy;
                                            break;

                                        case 1:
                                            difficulty = GameDifficulty.Normal;
                                            break;

                                        case 2:
                                            difficulty = GameDifficulty.Hard;
                                            break;

                                        case 4:
                                            diffmenu.Escaped = true;
                                            break;
                                    }
                                    if (diffmenu.SelectedNum >= 0 & diffmenu.SelectedNum <= 2)
                                    {
                                        engine = new GameEngine(difficulty, mapToLoad, this);
                                        engine.Initialize();
                                        SetMainMode();
                                        gamemode = GameMode.GAME;
                                    }
                                }
                                if (diffmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;
                            case MenuMode.Settings:
                                settmenu.Update(gameTime);
                                if (settmenu.Choosed)
                                {
                                    switch (settmenu.SelectedNum)
                                    {
                                        case 0:
                                            ChangeMode(MenuMode.Language);
                                            break;

                                        case 1:
                                            ChangeMode(MenuMode.Nick);
                                            nicktextbox.SetText(Properties.Settings.Default.Nick);
                                            nicktextbox.Initialize();
                                            break;

                                        case 2:
                                            break;

                                        case 4:
                                            settmenu.Escaped = true;
                                            break;
                                    }
                                }
                                if (settmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;

                            case MenuMode.Language:
                                langlist.Update(gameTime);
                                langmenu.Update(gameTime);
                                if (langmenu.Choosed)
                                {
                                    switch (langmenu.SelectedNum)
                                    {
                                        case 0:
                                            LangListLoad();
                                            break;
                                        case 1:
                                            langmenu.Escaped = true;
                                            break;
                                    }
                                }
                                else if (langlist.Choosed)
                                {
									if (Locale.currentLang.filename != Locale.LanguageList[langlist.SelectedNum].filename & Locale.LoadLang(Locale.LanguageList[langlist.SelectedNum], true))
                                    {
										Properties.Settings.Default.Language = Locale.currentLang.filename;
                                        Properties.Settings.Default.Save();
                                        MenusInit();
                                        langlist.Escaped = true;
                                    }
                                }
                                if (langlist.Escaped | langmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;
                            case MenuMode.Nick:
                                nicktextbox.Update(gameTime);
                                nickmenu.Update(gameTime);
                                if (nickmenu.Choosed)
                                {
                                    if (nickmenu.SelectedNum == 2)
                                    {
                                        Properties.Settings.Default.Nick = nicktextbox.GetText();
                                        Properties.Settings.Default.Save();
                                    }
                                    nickmenu.Escaped = true;
                                }
                                if (nickmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;
                            case MenuMode.SnakeColor:
                                break;
                            case MenuMode.Instruct:
                                instrmenu.Update(gameTime);
                                if (instrmenu.Choosed | instrmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;

                            case MenuMode.About:
                                aboutmenu.Update(gameTime);
                                if (aboutmenu.Choosed | aboutmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;

                            case MenuMode.Exit:
                                quitmenu.Update(gameTime);
                                if (quitmenu.Choosed)
                                {
                                    switch (quitmenu.SelectedNum)
                                    {
                                        case 0:
                                            Exit();
                                            break;

                                        case 1:
                                            quitmenu.Escaped = true;
                                            break;
                                    }
                                }
                                if (quitmenu.Escaped)
                                {
                                    PrevMode();
                                }
                                break;
                        }
                        break;

                    case GameMode.GAME:
                        engine.Update(gameTime);
                        if (engine.gamestate == GameEngine.GameStates.EXIT)
                        {
                            engine.Dispose();
                            gamemode = GameMode.MENU;
                        }
                        break;
                    case GameMode.EDITOR:
                        mapeditor.Update(gameTime);
                        if (mapeditor.state == Sharpie.MapEditor.State.EXIT)
                        {
                            mapeditor.Dispose();
                            gamemode = GameMode.MENU;
                            Window.Title = WindowTitle;
                        }
                        break;
                }
            }
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        ///
        protected override void Draw(GameTime gameTime)
        {
            switch (gamemode)
            {
                case GameMode.MENU:
                    spriteBatch.Begin();
                    spriteBatch.Draw(menubackground, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), Color.LightGreen);
                    spriteBatch.Draw(logo, new Vector2(GraphicsDevice.Viewport.Width / 2, logo.Height / 3), null, Color.White, 0F, new Vector2(logo.Width / 2, logo.Height / 2), LogoScale, SpriteEffects.None, 0F);
                    spriteBatch.End();
                    switch (menumode.Last.Value)
                    {
                        case MenuMode.Main:
                            mainmenu.Draw(gameTime);
                            break;

                        case MenuMode.MapSelect:
                            mapmenu.Draw(gameTime);
                            break;

                        case MenuMode.CustMapSelect:
                            custmaplist.DrawBackground(gameTime);
                            custmapmenu.Draw(gameTime);
                            custmaplist.Draw(gameTime);
                            break;

                        case MenuMode.NoCustMap:
                            mapmenu.Draw(gameTime);
                            nocustmapsmenu.Draw(gameTime);
                            break;

                        case MenuMode.Difficulty:
                            diffmenu.Draw(gameTime);
                            break;

                        case MenuMode.Settings:
                            settmenu.Draw(gameTime);
                            break;

                        case MenuMode.Language:
                            langlist.DrawBackground(gameTime);
                            langmenu.Draw(gameTime);
                            langlist.Draw(gameTime);
                            break;

                        case MenuMode.Nick:
                            nickmenu.Draw(gameTime);
                            nicktextbox.Draw(gameTime);
                            break;

                        case MenuMode.SnakeColor:
                            scolormenu.Draw(gameTime);
                            break;
                        case MenuMode.Scores:
                            scoresmenu.Draw(gameTime);
                            break;

                        case MenuMode.Instruct:
                            instruct.Draw(gameTime);
                            spriteBatch.Begin();
                            Text.DrawShadowedText(spriteBatch, FontBig, Locale.String("STEERING") + ":", new Vector2(GraphicsDevice.Viewport.Width / 2 - 400 / 2, GraphicsDevice.Viewport.Height / 2 - 15), Color.White);
                            Text.DrawShadowedText(spriteBatch, FontNormal, Locale.String("ARROW_KEYS") + " - " + Locale.String("SNAKE_DIRECTION"), new Vector2(
								GraphicsDevice.Viewport.Width / 2 - 400 / 2,
								GraphicsDevice.Viewport.Height / 2 - 12 + FontBig.LineSpacing
								), Color.White);
                            Text.DrawShadowedText(spriteBatch, FontNormal, "ESC - " + Locale.String("PAUSE_MENU"), new Vector2(
								GraphicsDevice.Viewport.Width / 2 - 400 / 2,
								GraphicsDevice.Viewport.Height / 2 - 12 + FontBig.LineSpacing + FontNormal.LineSpacing
								), Color.White);
                            spriteBatch.End();
                            instrmenu.Draw(gameTime);
                            break;

                        case MenuMode.About:
                            about.Draw(gameTime);
                            spriteBatch.Begin();
                            Text.DrawShadowedText(spriteBatch, FontBig, "Sharpie", new Vector2(GraphicsDevice.Viewport.Width / 2 - 400 / 2, GraphicsDevice.Viewport.Height / 2 - 30), Color.White);
                            Text.DrawShadowedText(spriteBatch, FontNormal, Locale.String("VERSION") + " " + version, new Vector2(
								GraphicsDevice.Viewport.Width / 2 - 400 / 2,
								GraphicsDevice.Viewport.Height / 2 - 30 + FontBig.LineSpacing
								), Color.White);
                            spriteBatch.End();
                            aboutmenu.Draw(gameTime);
                            break;

                        case MenuMode.Exit:
                            quitmenu.Draw(gameTime);
                            break;
                    }
                    break;

                case GameMode.GAME:
                    engine.Draw(gameTime);
                    break;
                case GameMode.EDITOR:
                    mapeditor.Draw(gameTime);
                    break;
            }
            spriteBatch.Begin();
            if (version != "")
                Text.DrawShadowedText(spriteBatch, FontSmall, Locale.String("VERSION") + " " + version, new Vector2((int)2, (int)0), Color.White);
            spriteBatch.Draw(cursor, new Vector2(mouse.X, mouse.Y), curcolor);
            if (Touch.State != TouchLocationState.Released & Touch.State != TouchLocationState.Invalid)
            {
                spriteBatch.Draw(touchcircle, new Vector2(Touch.Position.X, Touch.Position.Y), Color.White);
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }

        public static void ChangeMode(MenuMode mode)
        {
            menumode.AddLast(mode);
        }

        public static void PrevMode()
        {
            if (menumode.Count > 1) menumode.RemoveLast();
        }

        private void SetMainMode()
        {
            while (menumode.Count > 1) menumode.RemoveLast();
        }

        private void LangListLoad()
        {
            Locale.ReloadLanguageList();
            List<string> entries = new List<string>();
            List<string> tooltips = new List<string>();
            Locale.ReadLangList();
            foreach (Language l in Locale.LanguageList)
            {
                if (l.lang != "") entries.Add(l.lang_en + " (" + l.lang + ")");
                else entries.Add(l.lang_en);
                tooltips.Add(Locale.String("AUTHOR") + ": " + l.author);
            }
            langlist.Entries = entries;
            langlist.Tooltips = tooltips;
        }
    }
}